home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / gfx / 3d / irit50src.lha / irit5 / prsr_lib / soc_srvr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-19  |  26.3 KB  |  721 lines

  1. /*****************************************************************************
  2. *   Sockets routines to handle socket io of an objects.                 *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.1, June 1993.  *
  5. *****************************************************************************/
  6.  
  7. #include <stdio.h>
  8. #include <sys/types.h>
  9.  
  10. #ifdef __UNIX__
  11. #if (defined(ultrix) && defined(mips)) || defined(_AIX) || defined(sgi)
  12. #    include <fcntl.h>
  13. #else
  14. #    include <sys/fcntl.h>
  15. #endif /* (ultrix && mips) || _AIX || sgi */
  16. #include <signal.h>
  17. #include <sys/socket.h>
  18. #if defined(__hpux) || defined(sun)
  19. #    include <sys/file.h>
  20. #endif /* __hpux || sun */
  21. #include <netinet/in.h>
  22. #include <netdb.h>
  23. #endif /* __UNIX__ */
  24.  
  25. #ifdef __WINNT__
  26. #include <stdlib.h>
  27. #include <windows.h>
  28. #include <winsock.h>
  29. #include <io.h>
  30. #endif /* __WINNT__ */
  31.  
  32. #ifdef AMIGA
  33. #ifdef __SASC
  34. #include <dos.h>
  35. #endif
  36. #include <string.h>
  37. #include <exec/types.h>
  38. #include <exec/ports.h>
  39. #include <exec/memory.h>
  40. #include <dos/dostags.h>
  41. #include <proto/dos.h>
  42. #include <proto/exec.h>
  43. #endif /* AMIGA */
  44.  
  45. #include "irit_sm.h"
  46. #include "prsr_loc.h"
  47. #include "irit_soc.h"
  48.  
  49. #ifdef OS2GCC
  50. #define INCL_DOSPROCESS
  51. #include <os2.h>
  52. #endif /* OS2GCC */
  53.  
  54. static void SocketPrintError(char *Str);
  55. #ifdef __UNIX__
  56. #if defined(_AIX) || defined(__hpux) || defined(sun)
  57. typedef void (*SignalFuncType)(int); 
  58. #else
  59. typedef void (*SignalFuncType)(void); 
  60. #endif /* _AIX || __hpux || sun */
  61. static void SocNoConnectionHandler(void);
  62. static void SocNoConnectionDummyHandler(void);
  63. #endif /* __UNIX__ */
  64.  
  65. /*****************************************************************************
  66. * DESCRIPTION:                                                               *
  67. * IO error print routine.                             *
  68. *                                                                            *
  69. * PARAMETERS:                                                                *
  70. *   Str:      To output to stderr as a message.                              *
  71. *                                                                            *
  72. * RETURN VALUE:                                                              *
  73. *   void                                                                     *
  74. *****************************************************************************/
  75. static void SocketPrintError(char *Str)
  76. {
  77. #   if defined(__UNIX__) || defined(OS2GCC) || defined(AMIGA)
  78.     perror(Str);
  79. #   endif /* __UNIX__ || OS2GCC */
  80. #   ifdef __WINNT__
  81.     fprintf(stderr, "iritserver: %s error %d\n", Str, WSAGetLastError());
  82. #   endif /* __WINNT__ */
  83. }
  84.  
  85. /*****************************************************************************
  86. * DESCRIPTION:                                                               M
  87. * Writes a single char to client's socket.                     M
  88. *                                                                            *
  89. * PARAMETERS:                                                                M
  90. *   Handler: The socket info handler index.                                  M
  91. *   c:       Character to write.                                             M
  92. *                                                                            *
  93. * RETURN VALUE:                                                              M
  94. *   void                                                                     M
  95. *                                                                            *
  96. * KEYWORDS:                                                                  M
  97. *   SocWriteChar, ipc                                                        M
  98. *****************************************************************************/
  99. void SocWriteChar(int Handler, char c)
  100. {
  101. #if defined(__UNIX__) || defined(__WINNT__)
  102.     int i;
  103.  
  104.     if (_IPStream[Handler].CommuSoc <= 0) {
  105.     IritPrsrFatalError("Attempt to write to a closed (broken!?) socket");
  106.     return;
  107.     }
  108.  
  109.     while ((i = send(_IPStream[Handler].CommuSoc, &c, 1, 0)) != 1) {
  110.     if (i < 0)                   /* Lost connection probably. */
  111.         SocServerCloseSocket(Handler);
  112.     IritSleep(10);
  113.     }
  114. #endif /* __UNIX__ || __WINNT__ */
  115. #ifdef OS2GCC
  116.     ULONG BytesWritten;
  117.     ULONG rc;
  118.  
  119.     rc = DosWrite(_IPStream[Handler].pipIrit, &c, 1, &BytesWritten);
  120. #endif /* OS2GCC */
  121. #ifdef AMIGA
  122.     struct IritMessage msg;
  123.  
  124.     msg.msg.mn_Node.ln_Type = NT_MESSAGE;
  125.     msg.msg.mn_ReplyPort = _IPStream[Handler].ReplySoc;
  126.     msg.nbytes = 1;
  127.     msg.txt[0] = c;
  128.     msg.msg.mn_Length = sizeof(struct IritMessage) - LINE_LEN_LONG + msg.nbytes;
  129.     PutMsg(_IPStream[Handler].CommuSoc, (struct Message *) &msg);
  130.     WaitPort(_IPStream[Handler].ReplySoc);
  131.     (void)GetMsg(_IPStream[Handler].ReplySoc);
  132. #endif /* AMIGA */
  133. }
  134.  
  135. /*****************************************************************************
  136. * DESCRIPTION:                                                               M
  137. * Writes a single line of line length characters.                 M
  138. *                                                                            *
  139. * PARAMETERS:                                                                M
  140. *   Handler: The socket info handler index.                                  M
  141. *   Line:       Line to write.                                               M
  142. *   LineLen:    Length of line to write.                                     M
  143. *                                                                            *
  144. * RETURN VALUE:                                                              M
  145. *   void                                                                     M
  146. *                                                                            *
  147. * KEYWORDS:                                                                  M
  148. *   SocWriteLine, ipc                                                        M
  149. *****************************************************************************/
  150. void SocWriteLine(int Handler, char *Line, int LineLen)
  151. {
  152. #if defined(__UNIX__) || defined(__WINNT__)
  153.     int i;
  154.  
  155.     if (_IPStream[Handler].CommuSoc <= 0) {
  156.     IritPrsrFatalError("Attempt to write to a closed (broken!?) socket");
  157.     return;
  158.     }
  159.  
  160.     while ((i = send(_IPStream[Handler].CommuSoc, Line,
  161.                                               LineLen, 0)) < LineLen) {
  162.     if (i < 0)                   /* Lost connection probably. */
  163.         SocServerCloseSocket(Handler);
  164.     IritSleep(10);
  165.     LineLen = LineLen - i;
  166.     Line = &Line[i];
  167.     }
  168. #endif /* __UNIX__ || __WINNT__ */
  169. #ifdef OS2GCC
  170.     ULONG BytesWritten;
  171.     ULONG rc;
  172.  
  173.     rc = DosWrite(_IPStream[Handler].pipIrit, Line,
  174.           LineLen, &BytesWritten);
  175. #endif /* OS2GCC */
  176. #ifdef AMIGA
  177.     struct IritMessage msg;
  178.  
  179.     msg.msg.mn_Node.ln_Type = NT_MESSAGE;
  180.     msg.msg.mn_ReplyPort = _IPStream[Handler].ReplySoc;
  181.     for ( ; LineLen>0; LineLen-=msg.nbytes, Line+=msg.nbytes) {
  182.     msg.nbytes = (LineLen > LINE_LEN_LONG) ? LINE_LEN_LONG : LineLen;
  183.     memcpy(msg.txt, Line, msg.nbytes);
  184.     msg.msg.mn_Length =
  185.         sizeof(struct IritMessage) - LINE_LEN_LONG + msg.nbytes;
  186.     PutMsg(_IPStream[Handler].CommuSoc, (struct Message *) &msg);
  187.     WaitPort(_IPStream[Handler].ReplySoc);
  188.     GetMsg(_IPStream[Handler].ReplySoc);
  189.     }
  190. #endif /* AMIGA */
  191. }
  192.  
  193. /*****************************************************************************
  194. * DESCRIPTION:                                                               M
  195. * Creates a server socket. Returns handler if successful. Also sets the      M
  196. * IRIT_SERVER_PORT environment variable to the allocated socket.         M
  197. *                                                                            *
  198. * PARAMETERS:                                                                M
  199. *   BinaryIPC:     Do we want to communicate text or binary?                   M
  200. *   Read:     Is this socket for read (TRUE) or write (FALSE).            M
  201. *                                                                            *
  202. * RETURN VALUE:                                                              M
  203. *   int:         Non negative handler if successful, -1 otherwise.           M
  204. *                                                                            *
  205. * KEYWORDS:                                                                  M
  206. *   SocServerCreateSocket, ipc                                               M
  207. *****************************************************************************/
  208. int SocServerCreateSocket(int BinaryIPC, int Read)
  209. {
  210.     int Handler;
  211.     static char Line[LINE_LEN];
  212.  
  213. #if defined(__UNIX__) || defined(__WINNT__)
  214.     int i, s;
  215.     struct sockaddr_in Sain;
  216.  
  217.     ZAP_MEM(&Sain, sizeof(struct sockaddr_in));
  218.     Sain.sin_addr.s_addr = htonl(INADDR_ANY);
  219.     Sain.sin_family = AF_INET;
  220. #endif /* __UNIX__ || __WINNT__ */
  221.  
  222. #if defined(__UNIX__) || defined(__WINNT__)
  223. #ifdef __WINNT__
  224.     {
  225.     WSADATA WSAData;
  226.  
  227.     if ((s = WSAStartup(MAKEWORD(1, 1), &WSAData)) != 0 ||
  228.         LOBYTE(WSAData.wVersion) != 1 ||
  229.         HIBYTE(WSAData.wVersion) != 1) {
  230.         fprintf(stderr, "iritserver: WSAStartup: error %d\n",
  231.             WSAGetLastError());
  232.         return -1;
  233.     }
  234.     }
  235. #endif
  236.  
  237.     /* Create the socket, make it nonblocking if Read, and bind. */
  238.     if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  239.     fprintf(stderr, "iritserver: socket");
  240.     return -1;
  241.     }
  242.  
  243.     if (Read) {
  244. #ifdef __UNIX__
  245. #ifdef __hpux
  246.         if (fcntl(s, F_SETFL, O_NDELAY) < 0) {
  247. #else
  248.         if (fcntl(s, F_SETFL, FNDELAY) < 0) {
  249. #endif /* __hpux */
  250.         SocketPrintError("iritclient: fcntl");
  251.         return -1;
  252.         }
  253. #endif /* __UNIX__ */
  254.     }
  255.  
  256.     Sain.sin_port = 0;
  257.     if (bind(s, (struct sockaddr *) &Sain, sizeof(struct sockaddr_in)) < 0) {
  258.     fprintf(stderr, "iritserver: bind");
  259.     return -1;
  260.     }
  261.  
  262.     if (listen(s, 5) < 0) {
  263.     fprintf(stderr, "iritserver: listen");
  264.     return -1;
  265.     }
  266.  
  267.     i = sizeof(struct sockaddr_in);
  268.     if (getsockname(s, (struct sockaddr *) &Sain, &i) < 0) {
  269.     fprintf(stderr, "iritserver: getsockname");
  270.     return -1;
  271.     }
  272.  
  273.     sprintf(Line, "IRIT_SERVER_PORT=%d", Sain.sin_port);
  274.     putenv(Line);
  275.  
  276. #ifdef __UNIX__
  277.     signal(SIGPIPE, (SignalFuncType) SocNoConnectionHandler);
  278. #endif /* __UNIX__ */
  279.  
  280.     Handler = IritPrsrOpenStreamFromSocket(0, FALSE, BinaryIPC);
  281.     _IPStream[Handler].MasterSoc = s;
  282. #endif /* __UNIX__ || __WINNT__ */
  283.  
  284. #ifdef OS2GCC
  285.     static int
  286.     PipeCount = 0;
  287.     HPIPE pipIrit;
  288.     ULONG rc;
  289.  
  290.     sprintf(Line, "\\pipe\\irit_%d", ++PipeCount);
  291.  
  292.     rc = DosCreateNPipe(Line,
  293.             &pipIrit,
  294.             NP_ACCESS_DUPLEX | NP_NOWRITEBEHIND,
  295.             NP_WAIT | NP_TYPE_BYTE | NP_READMODE_BYTE | 1,
  296.             IRIT_PIPE_BUFFER_SIZE,
  297.             IRIT_PIPE_BUFFER_SIZE,
  298.             0);
  299.  
  300.     if (rc != 0) {
  301.     fprintf(stderr,
  302.         "DosCreateNPipe: error in creating %s\n", Line);
  303.     return FALSE;
  304.     }
  305.  
  306.     Handler = IritPrsrOpenStreamFromSocket(0, FALSE, BinaryIPC);
  307.     _IPStream[Handler].pipIrit = pipIrit;
  308.  
  309.     sprintf(Line, "IRIT_SERVER_PORT=\\pipe\\irit_%d", PipeCount);
  310.     putenv(Line);
  311. #endif /* OS2GCC */
  312. #ifdef AMIGA
  313.     static int portno = 0;
  314.     char *name;
  315.  
  316.     Handler = IritPrsrOpenStreamFromSocket(0, FALSE, BinaryIPC);
  317.     _IPStream[Handler].CommuSoc = CreateMsgPort();
  318.     if (_IPStream[Handler].CommuSoc) {
  319.     name = malloc(16);
  320.     sprintf(name, "IRIT%d", portno++);
  321.     _IPStream[Handler].CommuSoc->mp_Node.ln_Name = name;
  322.     _IPStream[Handler].CommuSoc->mp_Node.ln_Pri = 0;
  323.     AddPort(_IPStream[Handler].CommuSoc);
  324.     _IPStream[Handler].ReplySoc = CreateMsgPort();
  325.     if (!_IPStream[Handler].ReplySoc) {
  326.         RemPort(_IPStream[Handler].CommuSoc);
  327.         DeleteMsgPort(_IPStream[Handler].CommuSoc);
  328.         _IPStream[Handler].CommuSoc = NULL;
  329.         return FALSE;
  330.     }
  331.     } else {
  332.     return FALSE;
  333.     }
  334.     sprintf(Line, "IRIT_SERVER_PORT=%s", name);
  335.     putenv(Line);
  336. #endif /* AMIGA */
  337.  
  338.     return Handler;
  339. }
  340.  
  341. /*****************************************************************************
  342. * DESCRIPTION:                                                               M
  343. * Accepts a client socket connection.                                        M
  344. *   This function blocks until a connection with a client is established.    M
  345. *                                                                            *
  346. * PARAMETERS:                                                                M
  347. *   Handler: The socket info handler index.                                  M
  348. *                                                                            *
  349. * RETURN VALUE:                                                              M
  350. *   int:     TRUE if succesful, FALSE otherwise.                             M
  351. *                                                                            *
  352. * KEYWORDS:                                                                  M
  353. *   SocServerAcceptConnection, ipc                                           M
  354. *****************************************************************************/
  355. int SocServerAcceptConnection(int Handler)
  356. {
  357. #if defined(__UNIX__) || defined(__WINNT__)
  358.     struct sockaddr_in ClientSain;
  359.     int i = SOC_TIME_OUT,
  360.     Len = sizeof(ClientSain);
  361.  
  362.     while (i-- > 0 &&
  363.        (_IPStream[Handler].CommuSoc =
  364.         accept(_IPStream[Handler].MasterSoc,
  365.            (struct sockaddr *) &ClientSain, &Len)) < 0)
  366.     IritSleep(10);
  367.  
  368.     return i > 0;
  369. #endif /* __UNIX__ || __WINNT__ */
  370. #ifdef OS2GCC
  371.     ULONG rc;
  372.  
  373.     if ((rc = DosConnectNPipe(_IPStream[Handler].pipIrit)) != 0) {
  374.     fprintf(stderr,
  375.         "DosConnectNPipe: error in connection %s\n",
  376.         getenv("IRIT_SERVER_PORT"));
  377.     return FALSE;
  378.     }
  379.  
  380.     _IPStream[Handler].CommuSoc = 1;
  381.  
  382.     return TRUE;
  383. #endif /* OS2GCC */
  384. #ifdef AMIGA
  385.     int len = -1;
  386.     char buf[4];
  387.     static int timescalled = 0;
  388.  
  389.     timescalled++;
  390.     buf[0] = '\0';
  391.     if (timescalled % 2) {
  392.     while (len < 0) {
  393.         len = GetVar(CLIENT_VAR, buf, sizeof(buf), GVF_GLOBAL_ONLY);
  394.         if (len < 0) {
  395. #ifdef __SASC
  396.         chkabort();
  397. #endif
  398.         Delay(50L);
  399.         }
  400.     }
  401.     DeleteVar(CLIENT_VAR, GVF_GLOBAL_ONLY);
  402.     }
  403.     return TRUE;
  404. #endif
  405. }
  406.  
  407. /*****************************************************************************
  408. * DESCRIPTION:                                                               M
  409. * Closes a server socket/connection.                                         M
  410. *                                                                            *
  411. * PARAMETERS:                                                                M
  412. *   Handler: The socket info handler index.                                  M
  413. *                                                                            *
  414. * RETURN VALUE:                                                              M
  415. *   void                                                                     M
  416. *                                                                            *
  417. * KEYWORDS:                                                                  M
  418. *   SocServerCloseSocket, ipc                                                M
  419. *****************************************************************************/
  420. void SocServerCloseSocket(int Handler)
  421. {
  422. #ifndef AMIGA
  423.     if (_IPStream[Handler].CommuSoc > 0) {
  424. #ifdef __UNIX__
  425.     char Line[LINE_LEN];
  426.  
  427.     /* Force the system to realize that the connection is down. This is */
  428.     /* a kluge to solve the time out problem that happens under unix.   */
  429.     IritSleep(1000);
  430.     signal(SIGPIPE, (SignalFuncType) SocNoConnectionDummyHandler);
  431.     send(_IPStream[Handler].CommuSoc, Line, LINE_LEN, 0);
  432.  
  433.     if (close(_IPStream[Handler].CommuSoc) != 0)
  434.         SocketPrintError("iritserver: close");
  435. #endif /* __UNIX__ */
  436. #ifdef __WINNT__
  437.     closesocket(_IPStream[Handler].CommuSoc);
  438. #endif /* __WINNT__ */
  439. #ifdef OS2GCC
  440.     DosClose(_IPStream[Handler].pipIrit);
  441. #endif /* OS2GCC */
  442.     }
  443. #else /* AMIGA */
  444.     if (_IPStream[Handler].CommuSoc) {
  445.     RemPort(_IPStream[Handler].CommuSoc);
  446.     free(_IPStream[Handler].CommuSoc->mp_Node.ln_Name);
  447.     _IPStream[Handler].CommuSoc->mp_Node.ln_Name = NULL;
  448.     DeleteMsgPort(_IPStream[Handler].CommuSoc);
  449.     _IPStream[Handler].CommuSoc = NULL;
  450.     if (_IPStream[Handler].ReplySoc) {
  451.         DeleteMsgPort(_IPStream[Handler].ReplySoc);
  452.     }
  453.     }
  454. #endif /* AMIGA */
  455. }
  456.  
  457. /*****************************************************************************
  458. * DESCRIPTION:                                                               M
  459. * Returns TRUE if connection is alive and active.                 M
  460. *                                                                            *
  461. * PARAMETERS:                                                                M
  462. *   Handler: The socket info handler index.                                  M
  463. *                                                                            *
  464. * RETURN VALUE:                                                              M
  465. *   int:         TRUE if connection to client exists.                        M
  466. *                                                                            *
  467. * KEYWORDS:                                                                  M
  468. *   SocServerActive, ipc                                                     M
  469. *****************************************************************************/
  470. int SocServerActive(int Handler)
  471. {
  472. #ifndef AMIGA
  473.     return _IPStream[Handler].CommuSoc > 0;
  474. #else
  475.     return _IPStream[Handler].CommuSoc != 0;
  476. #endif /* AMIGA */
  477. }
  478.  
  479. #ifdef __UNIX__
  480. /*****************************************************************************
  481. * DESCRIPTION:                                                               *
  482. * Cleans the server socket in case of a broken pipe.                 *
  483. *                                                                            *
  484. * PARAMETERS:                                                                *
  485. *   None                                                                     *
  486. *                                                                            *
  487. * RETURN VALUE:                                                              *
  488. *   void                                                                     *
  489. *****************************************************************************/
  490. static void SocNoConnectionHandler(void)
  491. {
  492.     signal(SIGPIPE, (SignalFuncType) SocNoConnectionHandler);
  493.     _IPParserAbort(IP_ERR_SOCKET_BROKEN, "");
  494. }
  495.  
  496. /*****************************************************************************
  497. * DESCRIPTION:                                                               *
  498. * Dummy handler.                                                             *
  499. *                                                                            *
  500. * PARAMETERS:                                                                *
  501. *   None                                                                     *
  502. *                                                                            *
  503. * RETURN VALUE:                                                              *
  504. *   void                                                                     *
  505. *****************************************************************************/
  506. static void SocNoConnectionDummyHandler(void)
  507. {
  508. }
  509. #endif /* __UNIX__ */
  510.  
  511. /*****************************************************************************
  512. * DESCRIPTION:                                                               M
  513. * Attempts to write an object to a socket.                     M
  514. *                                                                            *
  515. * PARAMETERS:                                                                M
  516. *   Handler: The socket info handler index.                                  M
  517. *   PObj:     Object to write to the client's socket.                        M
  518. *                                                                            *
  519. * RETURN VALUE:                                                              M
  520. *   void                                                                     M
  521. *                                                                            *
  522. * KEYWORDS:                                                                  M
  523. *   SocWriteOneObject, ipc                                                   M
  524. *****************************************************************************/
  525. void SocWriteOneObject(int Handler, IPObjectStruct *PObj)
  526. {
  527.     char *ErrorMsg;
  528.  
  529.     if (IP_IS_UNDEF_OBJ(PObj)) {
  530.     fprintf(stderr, "Socket: Attempt to write an undefined object.\n");
  531.     return;
  532.     }
  533.     if (IP_IS_POLY_OBJ(PObj) && PObj -> U.Pl == NULL) {
  534.     fprintf(stderr, "Socket: Attempt to write an empty poly object.\n");
  535.     return;
  536.     }
  537.  
  538.     IritPrsrPutObjectToHandler(Handler, PObj);
  539.  
  540.     if (IritPrsrParseError(_IPStream[Handler].LineNum, &ErrorMsg)) {
  541.     fprintf(stderr, "Socket: %s\n", ErrorMsg);
  542.     }
  543. }
  544.  
  545. /*****************************************************************************
  546. * DESCRIPTION:                                                               M
  547. *   Executes the given program and connect to it io ports.                   M
  548. *                                                                            *
  549. * PARAMETERS:                                                                M
  550. *   Program:    Name of program to execute. Name can be NULL, in which the   M
  551. *               user is prompt to execute the program manually.             M
  552. *   PrgmInput:  A handler to the Program's input channel.             M
  553. *   PrgmOutput: A handler to the Program's output channel.             M
  554. *   IsBinary:   If TRUE sets channels to binary, if FALSE channels are text. M
  555. *                                                                            *
  556. * RETURN VALUE:                                                              M
  557. *   int:        TRUE, if succesful, FALSE otherwise.                         M
  558. *                                                                            *
  559. * KEYWORDS:                                                                  M
  560. *   IritPrsrSrvrExecAndConnect                                               M
  561. *****************************************************************************/
  562. int IritPrsrSrvrExecAndConnect(char *Program,
  563.                    int *PrgmInput,
  564.                    int *PrgmOutput,
  565.                    int IsBinary)
  566. {
  567.     int Input, Output;
  568.     char Line[LINE_LEN];
  569.     IPObjectStruct *PObj;
  570. #ifdef AMIGA
  571.     char buf[4];
  572.  
  573.     buf[0] = '\0';
  574.     SetVar(SERVER_VAR, buf, -1, GVF_GLOBAL_ONLY);
  575. #endif
  576.     if ((Input = SocServerCreateSocket(IsBinary, FALSE)) < 0)
  577.     return FALSE;
  578.  
  579.     if (Program != NULL && strlen(Program) > 0) {
  580. #if defined(__UNIX__)
  581.     char DisplayCommand[LINE_LEN];
  582.     
  583.     sprintf(DisplayCommand, "%s &", Program);
  584.     if (system(DisplayCommand) < 0) {
  585.         /* This, in fact, is not working since system does not return    */
  586.         /* error code of display device.                     */
  587.         sprintf(Line, "system: Failed to fork \"%s\"\n", Program);
  588.         IritPrsrFatalError(Line);
  589.         return FALSE;
  590.     }
  591. #else
  592. #if defined(__WINNT__) || defined(OS2GCC)
  593.     char DisplayCommand[LINE_LEN];
  594.  
  595.     sprintf(DisplayCommand, "start %s", Program);
  596.     system(DisplayCommand);
  597. #else
  598. #ifdef AMIGA
  599.     int HaveDisplay;
  600.     BPTR f;
  601.  
  602.     f = Open("*", MODE_OLDFILE);
  603.     HaveDisplay = !SystemTags(Program, SYS_Input,  NULL,
  604.                        SYS_Output, f,
  605.                        SYS_Asynch, TRUE,
  606.                        TAG_END);
  607.     /* SystemTags will always return success for programs run
  608.        asynchronously, so wait a bit and then check if the synchronization
  609.        environment variable created by the client exists. If not, we
  610.        probably failed to start the program.
  611.     */
  612.     Delay(150L);
  613.     if (GetVar(CLIENT_VAR, buf, sizeof(buf), GVF_GLOBAL_ONLY) < 0) {
  614.         HaveDisplay = FALSE;
  615.     }
  616.     if (!HaveDisplay){
  617.         fprintf(stderr,
  618.             "Irit: Startup your program - I am waiting...\n\nsetenv IRIT_SERVER_PORT %s\n\n",
  619.             getenv("IRIT_SERVER_PORT"));
  620.     }
  621. #endif /* AMIGA */
  622. #endif /* __WINNT__ || OS2GCC */
  623. #endif /* __UNIX__ || AMIGA */
  624.     }
  625.     else
  626.     fprintf(stderr,
  627.         "Irit: Startup your program - I am waiting...\n\nsetenv IRIT_SERVER_PORT %s\n\n",
  628.         getenv("IRIT_SERVER_PORT"));
  629.  
  630.     if (!SocServerAcceptConnection(Input))
  631.     return FALSE;
  632.  
  633.     /* Send on open channel the name of the port for the other direction. */
  634.     if ((Output = SocServerCreateSocket(IsBinary, TRUE)) < 0)
  635.     return FALSE;
  636.  
  637.     sprintf(Line, "IRIT_SERVER_PORT=%s", getenv("IRIT_SERVER_PORT"));
  638.     PObj = GenSTRObject(Line);
  639.     SocWriteOneObject(Input, PObj);
  640.     IPFreeObject(PObj);
  641.  
  642.     if (!SocServerAcceptConnection(Output))
  643.     return FALSE;
  644.  
  645.     fprintf(stderr, "Connection established to \"%s\"\n",
  646.         Program == NULL ? "?" : Program);
  647.  
  648.     *PrgmInput = Input;
  649.     *PrgmOutput = Output;
  650.  
  651.     return TRUE;
  652. }
  653.  
  654. /*****************************************************************************
  655. * DESCRIPTION:                                                               M
  656. *   Optionally kill and close channels to another process.                   M
  657. *                                                                            *
  658. * PARAMETERS:                                                                M
  659. *   Kill:       If TRUE, send a KILL message to the other process.           M
  660. *   PrgmInput:  A handler to the Program's input channel.             M
  661. *   PrgmOutput: A handler to the Program's output channel.             M
  662. *                                                                            *
  663. * RETURN VALUE:                                                              M
  664. *   int:        TRUE, if succesful, FALSE otherwise.                         M
  665. *                                                                            *
  666. * KEYWORDS:                                                                  M
  667. *   IritPrsrSrvrKillAndDisConnect                                            M
  668. *****************************************************************************/
  669. int IritPrsrSrvrKillAndDisConnect(int Kill, int PrgmInput, int PrgmOutput)
  670. {
  671.     IPObjectStruct
  672.     *PObj = GenStrObject("COMMAND_", Kill ? "EXIT" : "DISCONNECT", NULL);
  673.  
  674.     SocWriteOneObject(PrgmInput, PObj);
  675.     IPFreeObject(PObj);
  676.  
  677.     SocServerCloseSocket(PrgmInput);
  678.     SocServerCloseSocket(PrgmOutput);
  679.  
  680.     return TRUE;
  681. }
  682.  
  683. #ifdef DEBUG_SERVER
  684.  
  685. /*****************************************************************************
  686. * DESCRIPTION:                                                               *
  687. * Simple test for the server - reads file and dumps one object every key.    *
  688. *****************************************************************************/
  689. void main(int argc, char ** argv)
  690. {
  691.     int Handler, PrgmInput, PrgmOutput;
  692.     FILE
  693.     *f = argc == 2 ? fopen(argv[1], "r") : stdin;
  694.     IPObjectStruct *PObj,
  695.         *PObjClear = IPAllocObject("_COMMAND_", IP_OBJ_STRING, NULL),
  696.     *PObjs = IritPrsrGetObjects(f);
  697.  
  698.     if (argc == 2)
  699.     fclose(f);
  700.     strcpy(PObjClear -> U.Str, "CLEAR");
  701.  
  702.     Handler = IritPrsrSrvrExecAndConnect("x11drvs", &PrgmInput, &PrgmOutput,
  703.                      TRUE);
  704.  
  705.     while (TRUE) {
  706.     for (PObj = PObjs; PObj != NULL; PObj = PObj -> Pnext) {
  707.         fprintf(stderr, "Press return to send data.\n");
  708.         getchar();
  709.         SocWriteOneObject(Handler, PObj);
  710.     }
  711.  
  712.     fprintf(stderr, "Done. Press return to send clear.\n");
  713.     getchar();
  714.     SocWriteOneObject(Handler, PObjClear);
  715.     }
  716.  
  717.     IritPrsrSrvrKillAndDisConnect(TRUE, PrgmInput, PrgmOutput);
  718. }
  719.  
  720. #endif /* DEBUG_SERVER */
  721.